
/**
 * AppleIIGo
 * FDI Disk Image class
 * (C) 2008 by Marc S. Ressl (mressl@umich.edu)
 * Released under the GPL
 */

#include "FloppyDiskImage.h"

#ifndef FDIDISKIMAGE_H
#define FDIDISKIMAGE_H

#define FDIHEADER_BLOCKBYTENUM			0x200
#define FDIHEADER_FIRSTBLOCKTRACKNUM	180

#define FDIPATHSUFFIX				" (Autosaved).fdi"

#define FDISIGNATURE				"Formatted Disk Image File"
#define FDICREATOR					"AppleIIGo " APPLEIIGO_VERSION " (Build " \
									APPLEIIGO_BUILD ")"
#define FDIVERSION					0x200

typedef enum {
	FDIDISKTYPE_8_0,
	FDIDISKTYPE_5_25,
	FDIDISKTYPE_3_5,
	FDIDISKTYPE_3_0,
};
	
#define FDIFLAGS_WRITEPROTECTED		(1 << 0)
#define FDIFLAGS_INDEXSYNC			(1 << 1)

typedef enum {
	FDITPI_48,
	FDITPI_67,
	FDITPI_96,
	FDITPI_100,
	FDITPI_135,
	FDITPI_192,
};

#define FDITRACKTYPE_BLANK			0x00
#define FDITRACKTYPE_250KBPS		0xd2
#define FDITRACKTYPE_500KBPS		0xd4
#define FDITRACKTYPE_281_25KBPS		0xd5
#define FDITRACKTYPE_312_5KBPS		0xd6
#define FDITRACKTYPE_343_75KBPS		0xd7
#define FDITRACKTYPE_375KBPS		0xd8

struct FdiHeaderTrackType {
	UINT8 type;
	UINT8 pageNum;
};

struct FdiHeaderType {
	char signature[27];
	char creator[30];
	char crlf[2];
	char comment[80];
	char eof;
	UINT16 version;
	UINT16 ltrack;
	UINT8 lhead;
	UINT8 type;
	UINT8 rotspeed;
	UINT8 flags;
	UINT8 tpi;
	UINT8 headwidth;
	UINT16 reserved;
	struct FdiHeaderTrackType tracks[180 + 256];
};

struct FdiTrackType {
	UINT32 bitNum;
	UINT32 bitIndex;
};

class FDIDiskImage : public FloppyDiskImage {
public:
	static bool isDiskImageValid(UINT32 diskType, char * diskImagePath);
	
	FDIDiskImage(UINT32 diskType, char * diskImagePath);
	~FDIDiskImage();
	
	static bool writeDiskImage(FloppyDiskImage * diskImage);

protected:
	static bool readFdiHeader(UINT32 diskType,
							  FILE * diskImageFile,
							  UINT32 * fdiTrackNum,
							  struct FdiHeaderTrackType * fdiHeaderTracks,
							  bool * isWriteProtectionForced);
	
	bool readDiskImageTrack(UINT32 diskImageTrackIndex, 
							struct FdiHeaderTrackType * fdiHeaderTrack,
							bool isSetTrackBitNum);
	bool readDiskImage(UINT32 diskType, bool * isWriteProtectionForced,
					   bool isSetTrackBitNum);

	static void setFdiHeaderTrack(FloppyDiskImage * diskImage,
								  struct FdiHeaderTrackType * fdiHeaderTrack);
	static bool writeFdiHeader(FILE * diskImageFile,
							   FloppyDiskImage * diskImage);
	static bool writeDiskImageTrack(UINT32 trackIndex, UINT32 headIndex,
									FILE * diskImageFile,
									FloppyDiskImage * diskImage);
	static bool writeDiskImage(FILE * diskImageFile,
							   FloppyDiskImage * diskImage);
};

#endif
